package com.itlong.cloud.operate.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.operate.*;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.app.robot.AppProjectRobotInfoVO;
import com.itlong.cloud.POJO.VO.operate.*;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.PropertyPublicRoleEnum;
import com.itlong.cloud.operate.dao.IOperateDeveloperAuthDao;
import com.itlong.cloud.operate.dao.IOperatePropertyAccountDao;
import com.itlong.cloud.operate.service.IOperatePropertyAccountService;
import com.itlong.cloud.property.dao.IPropertyFunctionDao;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.NumberHandlerUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * <desc>
 * 物业账号处理接口实现
 * </desc>
 *
 * @createDate 2017-10-25.
 */
@Service
@RefreshScope
public class OperatePropertyAccountServiceImpl implements IOperatePropertyAccountService {

    private static Logger LOG = LoggerFactory.getLogger(OperatePropertyAccountServiceImpl.class);

    ExecutorService cachedThreadPool = Executors.newFixedThreadPool(10);

    @Value("${" + PlatformConstants.PROPERTY_USER_DEFAULT_PASSWORD + "}")
    String userDefaultPassword;

    @Autowired
    private MessageSender messageSender;

    @Autowired
    IOperatePropertyAccountDao iOperatePropertyAccountDao;

    @Autowired
    IPropertyFunctionDao iPropertyFunctionDao;
    //@Autowired
    //IPropertyUserInfoDao iPropertyUserInfoDao;

    @Autowired
    private IOperateDeveloperAuthDao iOperateDeveloperAuthDao;


    /**
     * <desc>
     * 获取公共管理员角色列表
     * <desc/>
     *
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperatePropertyRoleVO> getPropertyRoles() throws Exception {
        return iOperatePropertyAccountDao.getPropertyRoles();
    }

    /**
     * <desc>
     * 判断账号名是否已存在
     * <desc/>
     *
     * @param userName 账号名
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-25
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer checkPropertyAccount(String userName) throws Exception {
        return iOperatePropertyAccountDao.checkUserName(userName);
    }

    /**
     * <desc>
     * 判断某项目某角色用户是否已存在（一个项目的一个角色，只能有一个用户）
     * <desc/>
     *
     * @param projectId      项目编号
     * @param roleId         角色id
     * @param propertyUserId 排除物业用户id
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-31
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer checkProjectRoleExist(String projectId, String roleId, String propertyUserId) throws Exception {
        return iOperatePropertyAccountDao.checkProjectRoleExist(projectId, roleId, propertyUserId);
    }

    /**
     * <desc>
     * 添加新的物业账号
     * <desc/>
     *
     * @param saveDTO 新增物业账号
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-25
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer savePropertyAccount(OperatePropertyAccountSaveDTO saveDTO) throws Exception {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE1);
        //1.保存物业账号基础信息（property_user_info）
        PropertyUserInfoPO userInfoPO = new PropertyUserInfoPO();
        BeanUtils.copyProperties(saveDTO, userInfoPO);
        String userId = LogicIdUtil.bussinessId();
        userInfoPO.setUserId(userId);
        userInfoPO.setPassword(Md5EncryptUtil.md5(userDefaultPassword));
        if (StringUtils.isNotBlank(saveDTO.getEffectStartTime())) {
            userInfoPO.setEffectStartTime(dateFormat.parse(saveDTO.getEffectStartTime()));
            userInfoPO.setEffectEndTime(dateFormat.parse(saveDTO.getEffectEndTime()));
        }
        return this.doSavePropertyAccount(saveDTO, userInfoPO);
    }

    /**
     * <desc>
     * 添加新的物业账号(返回账号)
     * <desc/>
     *
     * @param saveDTO 新增物业账号信息
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-27
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public String savePropertyAccountSaas(OperatePropertyAccountSaveDTO saveDTO) throws Exception {
        //1.保存物业账号基础信息（property_user_info）
        PropertyUserInfoPO userInfoPO = new PropertyUserInfoPO();
        BeanUtils.copyProperties(saveDTO, userInfoPO);
        String userId = LogicIdUtil.bussinessId();
        userInfoPO.setUserId(userId);
        userInfoPO.setPassword(Md5EncryptUtil.md5(userDefaultPassword));
        this.doSavePropertyAccount(saveDTO, userInfoPO);
        return userId;
    }

    private Integer doSavePropertyAccount(OperatePropertyAccountSaveDTO saveDTO, PropertyUserInfoPO userInfoPO) throws Exception {
        List<RobotDeveloperAccountAuthPO> poList = new ArrayList<>();
        Integer result;
        Date nowTime = new Date();
        if (userInfoPO.getStatus() == null) {
            userInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
        }
        //独立开发者需生成appsecret
        if (PropertyPublicRoleEnum.DEVELOPER.getRoleId().equals(userInfoPO.getRoleId()) || PropertyPublicRoleEnum.SMART_CARD_DEVELOPER.getRoleId().equals(userInfoPO.getRoleId())
                || PropertyPublicRoleEnum.ROBOT_DEVELOPER.getRoleId().equals(userInfoPO.getRoleId())) {
            userInfoPO.setAppsecret(LogicIdUtil.getProjectKey());
        }

        //3,4,5权限的物业账户 姓名为其权限名称
        userInfoPO.setRealName(PropertyPublicRoleEnum.getRoleNameByRoleId(userInfoPO.getRoleId()));
        Date createTime = new Date();
        userInfoPO.setCreateTime(createTime);
        userInfoPO.setUpdateTime(createTime);
        Map<String, Object> params = SqlUtil.durableData(userInfoPO, PlatformConstants.TABLE_SAVE);
        result = iOperatePropertyAccountDao.save(params);

        //2.保存用户_角色_项目关系（property_role_project）
        List<PropertyRoleProjectPO> roleProjectPOS = new ArrayList<>();
        String[] projIds = StringHandlerUtil.splitString(saveDTO.getProjectIds());
        Date date = new Date();
        Date startdate = new Date();
        //设置开发者牌照过期时间，为当前时间+100年，表示长期有效 这个时候你我人都没有，
        date.setYear(220);
        for (String projId : projIds) {
            PropertyRoleProjectPO roleProjectPO = new PropertyRoleProjectPO();
            roleProjectPO.setProjectId(projId.trim());
            roleProjectPO.setRoleId(saveDTO.getRoleId());
            roleProjectPO.setUserId(userInfoPO.getUserId());
            roleProjectPO.setRobotWhiteListAuthStatus(0);
            //默认创建开发者账号时，有效期授权为100年，表示长期有效
            roleProjectPO.setEndTime(date);
            roleProjectPOS.add(roleProjectPO);

            if ("7".equals(saveDTO.getRoleId())) {
                //情况4 机器人白名单授权为 0否 并且机器人设备授权为 0否
                OperateDeveloperRobotAuthDeviceAuthDTO deviceAuthDTO = new OperateDeveloperRobotAuthDeviceAuthDTO();
                deviceAuthDTO.setProjectId(projId.trim());
                //获取项目下所有绑定的电梯
                List<OperateDeveloperAuthDeviceAuthListVO> listCloudElevator = iOperateDeveloperAuthDao.getDeviceListCloudElevator(SqlUtil.convertBeanToMapParams(deviceAuthDTO));
                //获取项目下所有绑定的门禁
                List<OperateDeveloperAuthDeviceAuthListVO> listCloudEntrance = iOperateDeveloperAuthDao.getDeviceListCloudEntrance(SqlUtil.convertBeanToMapParams(deviceAuthDTO));

                //处理门禁信息 云门禁云对接
                if (listCloudEntrance.size() == 0) {
                    RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                    po.setUserId(userInfoPO.getUserId());
                    po.setProjectId(projId.trim());
                    po.setDeviceType(3);
                    po.setDeviceUnique("");
                    po.setRobotId("");
                    po.setStatus(DataStatusEnum.NORMAL.getType());
                    po.setCreateTime(new Date());
                    poList.add(po);
                } else {
                    for (OperateDeveloperAuthDeviceAuthListVO operateDeveloperAuthDeviceAuthListVO : listCloudEntrance) { //机器人设备授权为 1否
                        RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                        po.setUserId(userInfoPO.getUserId());
                        po.setProjectId(projId.trim());
                        po.setDeviceType(3);
                        po.setDeviceUnique(operateDeveloperAuthDeviceAuthListVO.getDeviceUnique());
                        po.setRobotId("");
                        po.setStatus(DataStatusEnum.NORMAL.getType());
                        po.setCreateTime(new Date());
                        poList.add(po);
                    }
                }

                //处理机器人无感信息 多梯自动调度
                if (listCloudElevator.size() == 0) {
                    RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                    po.setUserId(userInfoPO.getUserId());
                    po.setProjectId(projId.trim());
                    po.setDeviceType(1);
                    po.setDeviceUnique("");
                    po.setRobotId("");
                    po.setStatus(DataStatusEnum.NORMAL.getType());
                    po.setCreateTime(new Date());
                    poList.add(po);
                } else {
                    for (OperateDeveloperAuthDeviceAuthListVO operateDeveloperAuthDeviceAuthListVO : listCloudElevator) { //机器人设备授权为 1否
                        RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                        po.setUserId(userInfoPO.getUserId());
                        po.setProjectId(projId.trim());
                        po.setDeviceType(1);
                        po.setDeviceUnique(operateDeveloperAuthDeviceAuthListVO.getDeviceUnique());
                        po.setRobotId("");
                        po.setStatus(DataStatusEnum.NORMAL.getType());
                        po.setCreateTime(new Date());
                        poList.add(po);
                    }
                }

                ////机器人对云端信息 单梯云对接
                if (listCloudElevator.size() == 0) {
                    RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                    po.setUserId(userInfoPO.getUserId());
                    po.setProjectId(projId.trim());
                    po.setDeviceType(2);
                    po.setDeviceUnique("");
                    po.setRobotId("");
                    po.setStatus(DataStatusEnum.NORMAL.getType());
                    po.setCreateTime(new Date());
                    poList.add(po);
                } else {
                    for (OperateDeveloperAuthDeviceAuthListVO operateDeveloperAuthDeviceAuthListVO : listCloudElevator) { //机器人设备授权为 1否
                        RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                        po.setUserId(userInfoPO.getUserId());
                        po.setProjectId(projId.trim());
                        po.setDeviceType(2);
                        po.setDeviceUnique(operateDeveloperAuthDeviceAuthListVO.getDeviceUnique());
                        po.setRobotId("");
                        po.setStatus(DataStatusEnum.NORMAL.getType());
                        po.setCreateTime(new Date());
                        poList.add(po);
                    }
                }
                //批量保存机器人开发者数据
                if (poList.size() > 0) {
                    iOperateDeveloperAuthDao.batchSaveDevelopInfo(poList);
                }
            }
        }
        if (!roleProjectPOS.isEmpty()) {
            result = iOperatePropertyAccountDao.saveRoleProject(roleProjectPOS);
        }

        //若创建用户绑定的项目只有一个，则将该项目下所有账号的物业名称更改
        if (projIds.length == 1){
            List<String> userIdStr = iOperatePropertyAccountDao.getUserIdByProjectId(Arrays.asList(projIds));
            iOperatePropertyAccountDao.updatePropertyNameByUserId(userIdStr, saveDTO.getPropertyName());
        }

        // 线下平台开发者的appsecret由相关内容加密得到，可解密 ；  取消一对一  一个项目对应多个开发者
        if (PropertyPublicRoleEnum.SMART_CARD_DEVELOPER.getRoleId().equals(userInfoPO.getRoleId())) {
            List<String> ProjectIds = null;
            if (saveDTO.getProjectIds() != null && saveDTO.getProjectIds().length() != 0) {
                ProjectIds = Arrays.asList(saveDTO.getProjectIds().split(","));
            }
            for (String projectId : ProjectIds) {
                Map<String, Object> licenceMap = new HashMap<>();
                licenceMap.put("projectId", projectId);
                licenceMap.put("appId", userInfoPO.getUserId());
                licenceMap.put("startTime", new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE1).format(startdate));
                licenceMap.put("endTime", new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE1).format(date));
                licenceMap.put("function", "1,2");
                String licence = DesEncryptUtil.aesEncryptSDK(JSON.toJSONString(licenceMap), userInfoPO.getAppsecret());
                iOperatePropertyAccountDao.updateProjectInfoLicenceByProjectId(projectId, licence, userInfoPO.getUserId(), userInfoPO.getRoleId());
            }

            //userInfoPO.setLicence(licence);

        }

        //保存用户套餐及角色资源关系
        if (PropertyPublicRoleEnum.ADMIN.getRoleId().equals(saveDTO.getRoleId())) {
            String projectId = projIds[0];
            String propertyPackageId = iOperatePropertyAccountDao.getDefaultPackage(projectId);
            List<String> propertyPackageFunctionId = iOperatePropertyAccountDao.getFunctionIds(propertyPackageId);
            //3.保存角色_项目_资源_关系（property_role_function）
            List<PropertyRoleFunctionPO> roleFunctionPOS = new ArrayList<>();
            String[] funcIds = StringHandlerUtil.splitString(saveDTO.getFunctionIds());
            List<String> functionIdList = Arrays.asList(funcIds);
            List<String> newFunctionIdList = new ArrayList<>(functionIdList);
            newFunctionIdList.addAll(propertyPackageFunctionId);
            for (String funcId : newFunctionIdList) {
                for (String projId : projIds) {
                    PropertyRoleFunctionPO functionPO = new PropertyRoleFunctionPO(
                            saveDTO.getRoleId(),
                            projId.trim(),
                            funcId.trim()
                    );
                    roleFunctionPOS.add(functionPO);
                    if (roleFunctionPOS.size() == 100) {
                        result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
                        roleFunctionPOS.clear();
                    }
                }
            }
            if (!roleFunctionPOS.isEmpty()) {
                result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
            }
        }else if (PropertyPublicRoleEnum.GROUP_ADMIN.getRoleId().equals(saveDTO.getRoleId())){
            this.asyncSaveUserFunction(Arrays.asList(projIds), saveDTO.getRoleId());
        }
        return result;
    }

    /**
     * <desc>
     * 更新单个物业账号信息事务
     * <desc/>
     *
     * @param updateDTO 物业账号更新信息
     * @return
     * @author Chunjian.G
     * @createDate 2018-02-25
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer updatePropertyAccountTrans(OperatePropertyAccountUpdateDTO updateDTO) throws Exception {
        List<RobotDeveloperAccountAuthPO> poList = new ArrayList<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE1);
        Integer result = null;
        Date nowTime = new Date();
        Date enddate = new Date();
        //设置开发者牌照过期时间，为当前时间+100年，表示长期有效 这个时候你我人都没有，
        enddate.setYear(220);
        //是否需要更新 物业_用户表（property_user_info）
        if (null != updateDTO.getStatus() || null != updateDTO.getDescription()) {
            PropertyUserInfoPO userInfoPO = new PropertyUserInfoPO();
            BeanUtils.copyProperties(updateDTO, userInfoPO);
            userInfoPO.setCreateTime(null);
            userInfoPO.setUpdateTime(new Date());
            if (StringUtils.isNotBlank(updateDTO.getEffectStartTime())) {
                userInfoPO.setEffectStartTime(dateFormat.parse(updateDTO.getEffectStartTime()));
                userInfoPO.setEffectEndTime(dateFormat.parse(updateDTO.getEffectEndTime()));
            }
            //取消线下平台开发者 一对一 ，改成 一个项目对多个开发者
         /*   if ("6".equals(updateDTO.getRoleId())) {
                Map<String, Object> licenceMap = iOperatePropertyAccountDao.getLicenceInfo(updateDTO.getUserId());
                licenceMap.put("projectId", updateDTO.getProjectIds());
                String appsecret = licenceMap.get("appsecret").toString();
                licenceMap.remove("appsecret");
                String licence = DesEncryptUtil.aesEncryptSDK(JSON.toJSONString(licenceMap), appsecret);
                userInfoPO.setLicence(licence);
            }*/
            Map<String, Object> params = SqlUtil.durableData(userInfoPO, PlatformConstants.TABLE_UPDATE);
            result = iOperatePropertyAccountDao.update(params);
        }
        //修改物业账号中所关联的物业名称
        if (null != updateDTO.getPropertyName()) {
            String[] projectIdArr = updateDTO.getProjectIds().split(",");
            //多项目时仅更改当前账号的物业名称
            if (projectIdArr.length > 1){
                List<String> userIdList  = new ArrayList<>();
                userIdList.add(updateDTO.getUserId());
                iOperatePropertyAccountDao.updatePropertyNameByUserId(userIdList, updateDTO.getPropertyName());

            }else if (projectIdArr.length == 1){
                //单个账号绑定单个项目时，找出只绑定了该项目的用户列表
                List<String> userIdStr = iOperatePropertyAccountDao.getUserIdByProjectId(Arrays.asList(projectIdArr));
                if (!userIdStr.isEmpty()){
                    iOperatePropertyAccountDao.updatePropertyNameByUserId(userIdStr, updateDTO.getPropertyName());
                }
            }
        }

        //物业账号旧数据
        String userRoleId = updateDTO.getRoleId();//角色类型id
        List<String> oldProjectIds = StringHandlerUtil.splitStringList(updateDTO.getOldManageProjectIds());
        List<String> newProjectIds = StringHandlerUtil.splitStringList(updateDTO.getProjectIds());
        if (null != updateDTO.getPropertyPackageIds()) {
            //删除物业账号-角色之前绑定的套餐
            iOperatePropertyAccountDao.deletePropertyUserPackage(updateDTO.getUserId());
            //重新插入套餐
            iOperatePropertyAccountDao.allotPackageUser(StringHandlerUtil.splitString(updateDTO.getPropertyPackageIds()), updateDTO.getUserId(),
                    DataStatusEnum.NORMAL.getType(), nowTime);
        }
        //是否需要更新 物业_角色_项目关联表（property_role_project）
        if (StringUtils.isNotBlank(updateDTO.getProjectIds())) {
            //删除前先取得原来的数据
            List<PropertyRoleProjectPO> list = iOperatePropertyAccountDao.getPropertyRoleProjectInfo(updateDTO.getUserId(), userRoleId);
            if (!newProjectIds.containsAll(oldProjectIds) || newProjectIds.size() != oldProjectIds.size()) {//新旧管辖项目不一致则删除重新插入
                //删除原有角色-项目关联
                iOperatePropertyAccountDao.removeRoleProject(updateDTO.getUserId(), userRoleId, oldProjectIds);
                //保存新的角色-项目关联
                List<PropertyRoleProjectPO> roleProjectPOS = new ArrayList<>();
                for (String projId : newProjectIds) {
                    PropertyRoleProjectPO roleProjectPO = new PropertyRoleProjectPO();
                    roleProjectPO.setProjectId(projId.trim());
                    roleProjectPO.setRoleId(userRoleId);
                    roleProjectPO.setUserId(updateDTO.getUserId());
                    //给新加项目授权有效时间为长期有效
                    roleProjectPO.setEndTime(enddate);
                    roleProjectPO.setRobotWhiteListAuthStatus(0);
                    for (PropertyRoleProjectPO propertyRoleProjectPO : list) {
                        if (propertyRoleProjectPO.getProjectId().equals(projId.trim())) {
                            roleProjectPO.setEndTime(propertyRoleProjectPO.getEndTime());
                            roleProjectPO.setCloudIntercomSdk(propertyRoleProjectPO.getCloudIntercomSdk());
                            roleProjectPO.setBluetoothSdk(propertyRoleProjectPO.getBluetoothSdk());
                            roleProjectPO.setQrCodeSdk(propertyRoleProjectPO.getQrCodeSdk());
                            roleProjectPO.setCloudElevatorApi(propertyRoleProjectPO.getCloudElevatorApi());
                            roleProjectPO.setDeviceAuth(propertyRoleProjectPO.getDeviceAuth());
                            roleProjectPO.setCloudIntercomAppidId(propertyRoleProjectPO.getCloudIntercomAppidId());
                            roleProjectPO.setRobotElevatorApi(propertyRoleProjectPO.getRobotElevatorApi());
                            roleProjectPO.setUpdateInfoUrl(propertyRoleProjectPO.getUpdateInfoUrl());
                            roleProjectPO.setStatusUrl(propertyRoleProjectPO.getStatusUrl());
                            roleProjectPO.setRobotWhiteListAuthStatus(propertyRoleProjectPO.getRobotWhiteListAuthStatus()==1?1:0);
                        }else {
                            //新增新项目的的开发者权限初始化
                            //修改物业账号后给机器开发者初始化该项目的权限
                            if ("7".equals(updateDTO.getRoleId())) {
                                //情况4 机器人白名单授权为 0否 并且机器人设备授权为 0否
                                OperateDeveloperRobotAuthDeviceAuthDTO deviceAuthDTO = new OperateDeveloperRobotAuthDeviceAuthDTO();
                                deviceAuthDTO.setProjectId(projId.trim());
                                //获取项目下所有绑定的电梯
                                List<OperateDeveloperAuthDeviceAuthListVO> listCloudElevator = iOperateDeveloperAuthDao.getDeviceListCloudElevator(SqlUtil.convertBeanToMapParams(deviceAuthDTO));
                                //获取项目下所有绑定的门禁
                                List<OperateDeveloperAuthDeviceAuthListVO> listCloudEntrance = iOperateDeveloperAuthDao.getDeviceListCloudEntrance(SqlUtil.convertBeanToMapParams(deviceAuthDTO));

                                //处理门禁信息 云门禁云对接
                                if (listCloudEntrance.size() == 0) {
                                    RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                                    po.setUserId(updateDTO.getUserId());
                                    po.setProjectId(projId.trim());
                                    po.setDeviceType(3);
                                    po.setDeviceUnique("");
                                    po.setRobotId("");
                                    po.setStatus(DataStatusEnum.NORMAL.getType());
                                    po.setCreateTime(new Date());
                                    poList.add(po);
                                } else {
                                    for (OperateDeveloperAuthDeviceAuthListVO operateDeveloperAuthDeviceAuthListVO : listCloudEntrance) { //机器人设备授权为 1否
                                        RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                                        po.setUserId(roleProjectPO.getUserId());
                                        po.setProjectId(projId.trim());
                                        po.setDeviceType(3);
                                        po.setDeviceUnique(operateDeveloperAuthDeviceAuthListVO.getDeviceUnique());
                                        po.setRobotId("");
                                        po.setStatus(DataStatusEnum.NORMAL.getType());
                                        po.setCreateTime(new Date());
                                        poList.add(po);
                                    }
                                }

                                //处理机器人无感信息 多梯自动调度
                                if (listCloudElevator.size() == 0) {
                                    RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                                    po.setUserId(updateDTO.getUserId());
                                    po.setProjectId(projId.trim());
                                    po.setDeviceType(1);
                                    po.setDeviceUnique("");
                                    po.setRobotId("");
                                    po.setStatus(DataStatusEnum.NORMAL.getType());
                                    po.setCreateTime(new Date());
                                    poList.add(po);
                                } else {
                                    for (OperateDeveloperAuthDeviceAuthListVO operateDeveloperAuthDeviceAuthListVO : listCloudElevator) { //机器人设备授权为 1否
                                        RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                                        po.setUserId(updateDTO.getUserId());
                                        po.setProjectId(projId.trim());
                                        po.setDeviceType(1);
                                        po.setDeviceUnique(operateDeveloperAuthDeviceAuthListVO.getDeviceUnique());
                                        po.setRobotId("");
                                        po.setStatus(DataStatusEnum.NORMAL.getType());
                                        po.setCreateTime(new Date());
                                        poList.add(po);
                                    }
                                }

                                ////机器人对云端信息 单梯云对接
                                if (listCloudElevator.size() == 0) {
                                    RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                                    po.setUserId(updateDTO.getUserId());
                                    po.setProjectId(projId.trim());
                                    po.setDeviceType(2);
                                    po.setDeviceUnique("");
                                    po.setRobotId("");
                                    po.setStatus(DataStatusEnum.NORMAL.getType());
                                    po.setCreateTime(new Date());
                                    poList.add(po);
                                } else {
                                    for (OperateDeveloperAuthDeviceAuthListVO operateDeveloperAuthDeviceAuthListVO : listCloudElevator) { //机器人设备授权为 1否
                                        RobotDeveloperAccountAuthPO po = new RobotDeveloperAccountAuthPO();
                                        po.setUserId(updateDTO.getUserId());
                                        po.setProjectId(projId.trim());
                                        po.setDeviceType(2);
                                        po.setDeviceUnique(operateDeveloperAuthDeviceAuthListVO.getDeviceUnique());
                                        po.setRobotId("");
                                        po.setStatus(DataStatusEnum.NORMAL.getType());
                                        po.setCreateTime(new Date());
                                        poList.add(po);
                                    }
                                }

                            }





                        }

                    }
                    roleProjectPOS.add(roleProjectPO);



                }
                //批量保存机器人开发者数据
                if (poList.size() > 0) {
                    iOperateDeveloperAuthDao.batchSaveDevelopInfo(poList);
                }
                result = iOperatePropertyAccountDao.saveRoleProject(roleProjectPOS);
                //删除原有角色菜单id
                iOperatePropertyAccountDao.removeRoleProjectFunction(userRoleId, oldProjectIds);
                //异步保存用户菜单，否则当选择项目过多时，可能会出现超时现象
                if (PropertyPublicRoleEnum.GROUP_ADMIN.getRoleId().equals(userRoleId)
                        || PropertyPublicRoleEnum.ADMIN.getRoleId().equals(userRoleId)){
                    this.asyncSaveUserFunction(newProjectIds, userRoleId);
                }
            }

            // 线下平台开发者的appsecret由相关内容加密得到，可解密 ；  取消一对一  一个项目对应多个开发者
            if (PropertyPublicRoleEnum.SMART_CARD_DEVELOPER.getRoleId().equals(updateDTO.getRoleId())) {
                List<String> ProjectIds = new ArrayList<>();
                if (updateDTO.getProjectIds() != null && updateDTO.getProjectIds().length() != 0) {
                    ProjectIds = Arrays.asList(updateDTO.getProjectIds().split(","));
                }
                for (String projectId : ProjectIds) {
                    Map<String, Object> licenceMap = iOperatePropertyAccountDao.getLicenceInfo(updateDTO.getUserId(),projectId);
                    licenceMap.put("projectId", projectId);
                    String appsecret = licenceMap.get("appsecret").toString();
                    licenceMap.remove("appsecret");
                    String licence = DesEncryptUtil.aesEncryptSDK(JSON.toJSONString(licenceMap), appsecret);
                    iOperatePropertyAccountDao.updateProjectInfoLicenceByProjectId(projectId, licence, updateDTO.getUserId(), updateDTO.getRoleId());
                }

                //userInfoPO.setLicence(licence);

            }


            //删除原有角色-项目-资源关联
            iOperatePropertyAccountDao.removeRoleProjectFunction(userRoleId, oldProjectIds);
            //保存新的角色-项目-资源关联（property_role_function）
            String[] funcIds = StringHandlerUtil.splitString(updateDTO.getFunctionIds());
            List<PropertyRoleFunctionPO> roleFunctionPOS = new ArrayList<>();
            for (String funcId : funcIds) {
                for (String projId : newProjectIds) {
                    PropertyRoleFunctionPO functionPO = new PropertyRoleFunctionPO(
                            userRoleId,
                            projId.trim(),
                            funcId.trim()
                    );
                    roleFunctionPOS.add(functionPO);
                    if (roleFunctionPOS.size() == 100) {
                        result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
                        roleFunctionPOS.clear();
                    }
                }
            }
            if (!roleFunctionPOS.isEmpty()) {
                result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
            }
        } else if (StringUtils.isNotBlank(updateDTO.getFunctionIds())) {//只更新角色-项目-资源关联（property_role_function）
            //删除原有角色-项目-资源关联
            iOperatePropertyAccountDao.removeRoleProjectFunction(userRoleId, oldProjectIds);
            //保存新的角色-项目-资源关联（property_role_function）
            String[] funcIds = StringHandlerUtil.splitString(updateDTO.getFunctionIds());
            List<PropertyRoleFunctionPO> roleFunctionPOS = new ArrayList<>();
            for (String funcId : funcIds) {
                for (String projId : oldProjectIds) {
                    PropertyRoleFunctionPO functionPO = new PropertyRoleFunctionPO(
                            userRoleId,
                            projId.trim(),
                            funcId.trim()
                    );
                    roleFunctionPOS.add(functionPO);
                    if (roleFunctionPOS.size() == 100) {
                        result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
                        roleFunctionPOS.clear();
                    }
                }
            }
            if (!roleFunctionPOS.isEmpty()) {
                result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
            }
            //如果操作为删除物业管理员功能则删除该项目下其他人员此功能权限
            //判断是否是物业管理员

            //查询更新之前的权限列表
            //对比出删除的权限

//            Map<String,Object> params = new HashMap<>();
//            params.put("roleId",userRoleId);
//            params.put("projectId",oldProjectIds);
//            List<String> roleFunctions = iPropertyFunctionDao.getFunctionIdsByRole(params);//旧的权限列表



        }
        return result;
    }

    /**
     * <desc>
     * 更新单个物业账号信息
     * <desc/>
     *
     * @param updateDTO 物业账号更新信息
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-26
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer updatePropertyAccount(OperatePropertyAccountUpdateDTO updateDTO) throws Exception {
        Integer result = this.updatePropertyAccountTrans(updateDTO);
        //若禁用物业账号则需要发送消息通知
        if (null != updateDTO.getStatus() && NumberHandlerUtil.isEqual(updateDTO.getStatus(), DataStatusEnum.BAN.getType())) {
            List<String> userIds = new ArrayList<>();
            userIds.add(String.format("%s%s", RedisConstant.PROPERTY_USER_REDIS_KEY, updateDTO.getUserId()));
            userIds.add(String.format("%s%s", RedisConstant.PROPERTY_APP_REDIS_USER_KEY, updateDTO.getUserId()));
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", userIds);
            messageSender.send(RabbitMQConstant.RABBITMQ_DELETE_CACHE_QUEUE, JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_USER_EXCHANGE, RabbitMQConstant.RABBITMQ_DELETE_CACHE_KEY);
        }
        return result;
    }

    /**
     * <desc>
     * 批量删除物业账号
     * <desc/>
     *
     * @param userIds 物业账号id列表，多个以英文逗号分隔
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-27
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer removePropertyAccounts(String userIds) throws Exception {
        //TODO 用户-项目关联如何删除
        //删除 property_user_info 中对应数据
        Integer result = iOperatePropertyAccountDao.removePropertyUsers(
                StringHandlerUtil.splitString(userIds)
        );
        return result;
    }

    /**
     * <desc>
     * 分页查询物业账号
     * <desc/>
     *
     * @param pageDTO 查询条件DTO
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-25
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<OperatePropertyAccountVO> getPage(OperatePropertyAccountGetPageDTO pageDTO) throws Exception {
        //分页对象
        Page<OperatePropertyAccountVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO, page);
        //查询
        List<OperatePropertyAccountVO> adminVOS = iOperatePropertyAccountDao.getSimplePage(params);
        Integer count = iOperatePropertyAccountDao.getCount(params);

        //判断是否已分配权限
//        List<String> projIdsParam = new ArrayList<>();
//        for (OperatePropertyAccountVO accountVO: adminVOS){
//            List<String> projIds = StringHandlerUtil.splitStringList(accountVO.getProjectIds());
//            if (projIds.isEmpty()){
//                accountVO.setHaveAuth(0);
//            }else {
//                projIdsParam.addAll(projIds);
//            }
//        }
//        if (!projIdsParam.isEmpty()){
//            List<PropertyRoleFunctionPO> functionPOS = iOperatePropertyAccountDao.checkRoleProjectFunction(projIdsParam);
//            if (null != functionPOS && !functionPOS.isEmpty()){
//                for (OperatePropertyAccountVO accountVO: adminVOS){
//                    if (accountVO.getHaveAuth() != null){
//                        continue;
//                    }
//                    for (PropertyRoleFunctionPO functionPO: functionPOS){
//                        if (accountVO.getProjectIds().indexOf(functionPO.getProjectId()) >= 0
//                                && accountVO.getRoleId().equals(functionPO.getRoleId())){
//                            accountVO.setHaveAuth(1);
//                            break;
//                        }
//                    }
//                }
//            }
//        }
        //判断账号是否已分配套餐
        List<String> userIdList = iOperatePropertyAccountDao.getUserIdList();
        adminVOS.forEach(item -> {
            if (userIdList.contains(item.getUserId())) {
                item.setHaveAuth(1);
            } else {
                item.setHaveAuth(0);
            }
        });
        //填充返回数据集
        page.setRows(adminVOS, count);
        return page;
    }

    /**
     * <desc>
     * 获取单个账户详情
     * <desc/>
     *
     * @param userId 账户id
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-26
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public OperatePropertyAccountDetailVO getDetail(String userId) throws Exception {
        return iOperatePropertyAccountDao.getDetail(userId);
    }

    /**
     * <desc>
     * 批量重置物业账号密码
     * <desc/>
     *
     * @param userIds 物业账号id列表，多个以英文逗号分隔
     * @return
     * @author Chunjian.G
     * @createDate 2017-10-27
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer resetPassword(String userIds) throws Exception {
        return iOperatePropertyAccountDao.resetPassword(
                StringHandlerUtil.splitString(userIds),
                Md5EncryptUtil.md5(userDefaultPassword)
        );
    }

    /**
     * <desc>
     * 分页获取物业开发者账号列表
     * <desc/>
     *
     * @param pageDTO 查询条件
     * @return
     * @author Qiang.S
     * @createDate 2018-06-29
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<OperatePropertyDeveloperVO> getDeveloperPage(OperatePropertyDeveloperGetPageDTO pageDTO) throws Exception {
        //分页对象
        Page<OperatePropertyDeveloperVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO, page);
        //查询
        List<OperatePropertyDeveloperVO> adminVOS = iOperatePropertyAccountDao.getDeveloperPage(params);
        Integer count = iOperatePropertyAccountDao.getDeveloperCount(params);
        //填充返回数据集
        page.setRows(adminVOS, count);
        return page;
    }

    /**
     * <desc>
     * 删除开发者账号
     * <desc/>
     *
     * @param userId    物业账号id
     * @param projectId 项目编号
     * @return
     * @author Qiang.S
     * @createDate 2018-09-07
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer removePropertyDeveloper(String userId, String projectId) throws Exception {
        //删除 property_user_info 中对应数据
        Integer result = iOperatePropertyAccountDao.removePropertyUsers(
                StringHandlerUtil.splitString(userId)
        );
        if (result == 0) {
            return result;
        }
        iOperatePropertyAccountDao.removePropertyDeveloper(userId);
        iOperatePropertyAccountDao.removeDeveloperRoleProjectFunction(projectId);
        return result;
    }

    /**
     * <desc>
     * 获取开发者下的项目及机器人信息
     * </desc>
     *
     * @param userId 开发者用户id
     * @return 项目及机器人信息
     * @Author Zhu.yj
     * @createDate 2020/8/25
     */
    @Override
    public List<AppProjectRobotInfoVO> getProjectRobotInfoByDeveloper(String userId, String loginType) throws Exception {

        Map<String, Object> params = new HashMap<>();
        List<AppProjectRobotInfoVO> robotInfoVOS = new ArrayList<>();
        if (("1").equals(loginType)) {//机器人开发者
            params.put("userId", userId);
            robotInfoVOS = iOperatePropertyAccountDao.getProjectRobotInfoByDeveloper(params);
            robotInfoVOS.forEach(item -> item.setRobotIdList(StringHandlerUtil.splitStringList(item.getRobotIdList() + "")));
        } else {//工程人员
            List<String> projectIds = iOperatePropertyAccountDao.getEngineerProjectIds(userId);
            if (projectIds.isEmpty()) {
                return robotInfoVOS;
            }
            params.put("projectIds", projectIds);
            robotInfoVOS = iOperatePropertyAccountDao.getProjectRobotInfoByDeveloper(params);
            robotInfoVOS.forEach(item -> item.setRobotIdList(StringHandlerUtil.splitStringList(item.getRobotIdList() + "")));
        }
        return robotInfoVOS;
    }

    /**
     * <desc>
     * 获取工程人员项目
     * </desc>
     *
     * @param userId 用户id
     * @return
     * @Author Zhu.yj
     * @createDate 2020/8/25
     */
    @Override
    public List<String> getEngineerProjectIds(String userId) throws Exception {
        return iOperatePropertyAccountDao.getEngineerProjectIds(userId);
    }

    /**
     * <desc>
     *      分页获取管理员列表
     * </desc>
     *
     * @param accountGetPageDTO 分页查询参数DTO
     * @return
     * @Author Zhu.yj
     * @createDate  2020/10/22
     */
    @Override
    public Page<OperatePropertyAccountVO> getAdminPage(OperatePropertyAccountGetPageDTO accountGetPageDTO) throws Exception {
        Page<OperatePropertyAccountVO> page = new Page<>();
        page.getPage().setPageSize(accountGetPageDTO.getPageSize());
        page.getPage().setCurrentPage(accountGetPageDTO.getCurrentPage());
        Map<String,Object> params = SqlUtil.convertBeanToMapParams(accountGetPageDTO);
        params.put("startSlip", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        page.setRows(iOperatePropertyAccountDao.getAdminPage(params), iOperatePropertyAccountDao.getAdminPageCount(params));
        return page;
    }

    /**
     * <desc>
     *      处理集团物业管理员旧数据菜单，收回不该有的权限
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/5/21
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer handlerGroupAdminFunction() throws Exception {

        Integer result = 0;
        List<String> projectIdList = iOperatePropertyAccountDao.getGroupAdminProjectList();
        //删除原有集团物业管理员角色菜单id
        iOperatePropertyAccountDao.removeRoleProjectFunction("3", projectIdList);

        //根据套餐给集团物业管理员分配菜单
        List<PropertyRoleFunctionPO> roleFunctionPOS = new ArrayList<>();
        for (String projectId : projectIdList){
            String propertyPackageId = iOperatePropertyAccountDao.getDefaultPackage(projectId);
            List<String> propertyPackageFunctionId = iOperatePropertyAccountDao.getFunctionIds(propertyPackageId);
            for (String functionId : propertyPackageFunctionId){
                PropertyRoleFunctionPO propertyRoleFunctionPO = new PropertyRoleFunctionPO("3", projectId, functionId);
                roleFunctionPOS.add(propertyRoleFunctionPO);
            }
        }
        if (!roleFunctionPOS.isEmpty()){
            result = iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
        }
        return result;
    }

    /**
     * <desc>
     *      保存角色菜单变更未异步保存
     * </desc>
     *
     * @param newProjectIds 变更的项目id
     * @param userRoleId 用户角色id
     * @return
     * @Author Zhu.yj
     * @createDate  2021/6/18
     */
    private void asyncSaveUserFunction(List<String> newProjectIds, String userRoleId){
        cachedThreadPool.execute(() ->{
            try{
                List<PropertyRoleFunctionPO> roleFunctionPOS = new ArrayList<>();
                for (String projectId : newProjectIds){
                    String propertyPackageId = iOperatePropertyAccountDao.getDefaultPackage(projectId);
                    List<String> propertyPackageFunctionId = iOperatePropertyAccountDao.getFunctionIds(propertyPackageId);
                    for (String functionId : propertyPackageFunctionId){
                        PropertyRoleFunctionPO propertyRoleFunctionPO = new PropertyRoleFunctionPO(userRoleId, projectId, functionId);
                        roleFunctionPOS.add(propertyRoleFunctionPO);
                    }
                }
                if (!roleFunctionPOS.isEmpty()){
                    iOperatePropertyAccountDao.saveRoleProjectFunction(roleFunctionPOS);
                }
            }catch (Exception e){
                LOG.error("【异步保存用户角色菜单失败】", e);
            }
        });
    }
}
